home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1996 February / macformat-034.iso / mac / Shareware City / Developers / simple-sockets-11-c / Simple Sockets 1.1 ƒ / Docs / Simple Sockets Manual.txt < prev    next >
Encoding:
Text File  |  1995-11-28  |  24.1 KB  |  628 lines  |  [TEXT/R*ch]

  1. Simple Sockets v 1.1
  2. Maintenance Release/Minor Upgrade
  3.  
  4. by Michael Trent.
  5.  
  6. 0. Manual Overview
  7. ~~~~~~~~~~~~~~~~~~
  8. (not quite a table of contents ... what with no page numbers and all)
  9.  
  10. Section                Topic
  11.  
  12.    1. . . . . . . . Introduction
  13.    2. . . . . . . . Distribution
  14.    3. . . . . . . . Installation
  15.    4. . . . . . . . Using Simple Sockets
  16.    5. . . . . . . . Simple Socket Routines
  17.    6. . . . . . . . Making Your Own Spin Routines
  18.    7. . . . . . . . Error Handling
  19.    8. . . . . . . . Suggested Reading List
  20.    9. . . . . . . . Simple Sockets License Agreement
  21.  
  22.  
  23. 1. Introduction
  24. ~~~~~~~~~~~~~~~
  25.  
  26. Simple Sockets arose out of an effort to port Sun Microsystems's RPCSRC 4.0 to
  27. the Macintosh operating system, using MacTCP for TCP/IP and UDP/IP support.  RPC
  28. relies on BSD UNIX socket calls for Inter Process Communication, like any good
  29. UNIX software should.  After tinkering with a number of socket solutions for the
  30. Macintosh (GUSI, some weird BSD source I received from University of Toronto, and
  31. so on), I decided to bite the bullet and simulate BSD sockets myself.
  32.  
  33. BSD compatibility has not been my primary goal however.  There are a number of
  34. facets of UNIX socket calls that are artifacts of earlier systems, remaining for
  35. backwards compatibility.  Also socket calls are designed to be more flexible than
  36. MacTCP can be.  So, some calls were simplified a bit for the sake of "progress".
  37.  
  38. As a result, most UNIX socket code won't compile without some modification
  39. (perhaps this makes the code useless to most people).  As time permits, I hope to
  40. close the gap between Simple Sockets and BSD sockets a little more.
  41.  
  42. On the off chance that someone might find this code useful, I am willingly giving
  43. all this code up into the Public Domain (my friends say "Sell It! Sell It!", but
  44. some perverse sense of virtue prevents me from charging money for anything I
  45. think is valuable - see my notoriously unpopular shareware program "CPU Reporter"
  46. for the corrollary: charge money for useless software).  If someone out there
  47. makes some changes to my code that are valuable additions or bug fixes, I'd love
  48. to hear about it, so I can update my master copies.  I hope to post updates to
  49. the Info-Mac archive when-and-if changes occur.
  50.  
  51. Of course, there are other BSD Socket implementations out there, some of them
  52. much better than my humble project (again: GUSI).  If you think this project has
  53. any value at all, please drop me a line, e- or snail- mail.  I can be reached at:
  54.  
  55.     Michael D. Trent
  56.     3302 Leopold Way #110
  57.     Madison, WI 53713
  58.     
  59.     work e-mail:  mtrent@epicsys.com
  60.     pleasure e-mail:  mtrent@msn.fullfeed.com
  61.  
  62. E-mail is preferred.  Please try my "pleasure" e-mail first — I do check it
  63. daily.
  64.  
  65. Oh, and this is version 1.1.  For a short list of changes, see the "Read Me
  66. First" file, if you haven't already.  If you get a chance, glance at "To Do" as
  67. well.  Enjoy!
  68.  
  69.  
  70. 2. Distribution
  71. ~~~~~~~~~~~~~~~
  72.  
  73. The Simple Sockets archive contains a number of important directories, including:
  74.  
  75. butil ƒ
  76.  
  77.     This directory includes a small library (butil.c) for supporting UNIX binary
  78.     utilities, such as bcmp, bcopy, bzero, and ffs.  These routines are handy,
  79.     even though they are far from optimized.
  80.     
  81. ip ƒ
  82.  
  83.     Here lies the networking code.  The bulk of the code can be found in ip.c,
  84.     the application level interface, and iplow.c, the MacTCP level interface. The
  85.     remaining files (ipdr.c, iperr.c, iptime.h, etc.) provide less important
  86.     features.
  87.  
  88. MacTCP Headers ƒ
  89.     
  90.     MacTCP header files for both the Universal Headers and for older pre-UH 
  91.     systems (i.e., THINK C 5.0.4).  See the “Headers ReadMe” in this directory
  92.     for more information.
  93.  
  94. Sample Apps ƒ
  95.  
  96.     A pair of sample applications have been provided to demonstrate Simple
  97.     Sockets in action.  The programs are probably buggy (I know of one problem
  98.     with the MacDayd program for sure), and do very little error reporting.  As
  99.     further evidence that I hacked them up in an hour, the code is a little hard
  100.     to read in spots.  Still, they should give one some idea of how to use the
  101.     Simple Sockets library.
  102.     
  103.     The sample programs, MacDay and MacDayd, are modeled after some examples in
  104.     Comer's Internetworking with TCP/IP vol III.  It seems that by pinging port
  105.     13 of any UNIX machine, that machine will tell you what time it thinks it is.
  106.     MacDay is a client program for the DAYTIME service, while MacDayd is a simple
  107.     server to allow one's Macintosh to accept DAYTIME queries.  These programs
  108.     are much less interesting than any Peter N. Lewis program.
  109.     
  110.  
  111. 3. Installation
  112. ~~~~~~~~~~~~~~~
  113.  
  114. Projects that use Simple Sockets need to have access to the butil ƒ and ip ƒ
  115. directories, as well as the headers for MacTCP.  Please refer to your compiler
  116. documentation for information on how to do this.  With Metrowerks CodeWarrior,
  117. three different strategies leap to my mind:
  118.  
  119.     1) Go into your project's preferences and set the project's Access Path to
  120.     include both directories.  While this works, it's a little tedious to do
  121.     once, never mind more several projects.
  122.  
  123.     2) Copy the directories into the application's project directory.  Of course,
  124.     if you are planning on writing lots of different Simple Sockets apps, you'll
  125.     be doing a lot of copying.
  126.  
  127.     3) Move the directories into the same folder as your Metrowerks compiler.  I
  128.     am personally quite fond of this solution, personally. 
  129.     
  130.     Note: Metrowerks Codewarrior 7.0 complicates this a little. The compiler no
  131.     longer looks for code in it's directory. You'll need to bury the routines in
  132.     one    of the compiler's subdirectories. See the Metrowerks documentation for
  133.     more details.
  134.  
  135. I believe these strategies will also work with the THINK compilers.
  136.  
  137.  
  138. 4. Using Simple Sockets
  139. ~~~~~~~~~~~~~~~~~~~~~~~
  140.  
  141. Using Simple Sockets is relatively easy, especially for those programmers with
  142. UNIX socket programming experience.  As I have alluded to already, some  Simple
  143. Socket routines are similar to, but not identical to, their UNIX counterparts.
  144. These differences will be explained later in this document.
  145.  
  146. The following files must be added to one's project: butil.c, ip.c, iperr.c, and
  147. iplow.c.  ipdr.c is optional, and is probably only necessary if you are porting
  148. some existing UNIX code to the Macintosh.
  149.  
  150. The file MacTCPCommonTypes.h must be #included before any ip files are.  For
  151. basic socket support, one would include:
  152.  
  153.      #include <MacTCPCommonTypes.h>
  154.      
  155.      #include "ip.h"
  156.      #include "iperr.h"
  157.  
  158. The Simple Sockets library must be initialized at run time before any socket
  159. routines are called.  The routine "InitMacTCP" opens the MacTCP driver and
  160. performs some additional house-keeping.  It shouldn't hurt to place InitMacTCP in
  161. your ToolBoxInit (or whatever) procedure.
  162.  
  163. Before the program terminates, it must make sure that all active sockets are
  164. closed. If a program quits without letting MacTCP know a stream is free, MacTCP
  165. can (and will!) crash the entire machine in a blaze of glory (if you don't
  166. believe me, force quit NCSA Telnet a few times).  To be safe, you can call
  167. "DisposeMacTCP" before quitting; DisposeMacTCP will close all remaining streams
  168. for you.  (Tip: Make sure you call this at the end of the program, and before any
  169. "ExitToShell" calls!)
  170.  
  171. All socket calls are asynchronous.  While a program is waiting for some network
  172. transaction to take place, the computer continues multi-tasking away.  This is
  173. provided in part by a secondary event loop (called a "Spin Routine"), which calls
  174. WaitNextEvent and provides basic event processing.  In order to provide spinning
  175. cursors or Dialogs with "Cancel" buttons, you must define your own Spin Routine;
  176. see "Making Your Own Spin Routines" below for more information.
  177.  
  178.  
  179. 5. Simple Socket Routines
  180. ~~~~~~~~~~~~~~~~~~~~~~~~~
  181.  
  182. At this time, only the routines in ip.c and ipdr.c are documented in this manual.
  183. Routines in other files are either fairly straight forward (IMHO) or they
  184. shouldn't be of much use to other people (e.g., iplow.c).  Other files may be
  185. documented here in the future.
  186.  
  187.  
  188. GENERAL ROUTINES
  189.  
  190.  
  191. InitMacTCP
  192.  
  193.     OSErr InitMacTCP(void)
  194.  
  195. InitMacTCP must be called by the application before making other calls to
  196. routines in the Simple Sockets library.  It initializes the MacTCP driver, clears
  197. the socket list, and sets the default spin routine.
  198.  
  199.  
  200. DisposeMacTCP
  201.  
  202.     void DisposeMacTCP(void)
  203.  
  204. DisposeMacTCP should be called before an application terminates, or when it is
  205. done with the MacTCP driver.  DisposeMacTCP closes all initialized sockets, and
  206. disposes sockets' buffer memory.
  207.  
  208.  
  209. SetSpin
  210.  
  211.     void SetSpin(Spin spinRoutine)
  212.  
  213. SetSpin sets the spin routine.  The spin routine is a secondary event loop called
  214. repeatedly by iplow.c while waiting for MacTCP calls to complete.  This allows
  215. other processes on the Macintosh to continue operating in their co-operative
  216. multi-tasking environment.  For information on writing your own spin routine, see
  217. "Making Your Own Spin Routines" below.
  218.  
  219.  
  220. ADDRESS CONVERSION AND LOOKUP ROUTINES
  221.  
  222.  
  223. num2dot
  224.  
  225.     void num2dot(unsigned long ip, char *dot)
  226.  
  227. num2dot is a small routine to convert an unsigned long ip number into the
  228. human-readable dot notation (e.g., 2421762054 becomes "144.89.40.6").  To be
  229. safe, dot should point to at least 16 bytes of memory.
  230.  
  231. num2dot isn't part of BSD UNIX sockets.
  232.  
  233.  
  234. ConvertStrToAddr
  235.  
  236.     OSErr ConvertStrToAddr(char *name, unsigned long *ipNum)
  237.  
  238. This routine converts strings to unsigned long ip numbers.  The string can
  239. contain either a dot notation ip address (e.g., "144.89.40.6"), or a DNS host
  240. name (e.g., "stu.beloit.edu").  It returns an OSErr passed on from MacTCP.
  241.  
  242. ConvertStrToAddr isn't part of BSD UNIX sockets.
  243.  
  244.  
  245. GetHostByName
  246.  
  247.     unsigned long GetHostByName(char *name)
  248.  
  249. GetHostByName emulates the UNIX routine by the same name (gethostbyname is
  250. #defined as GetHostByName).  Given a string containing a DNS name or a dot
  251. separated number, GetHostByName will return that host's unsigned long ip number. 
  252. If an error occurs, GetHostByName will return 0.
  253.  
  254.  
  255. GetProtoByName
  256.  
  257.     int GetProtoByName(char *name)
  258.  
  259. GetProtoByName roughly emulates the UNIX routine by the same name (getprotobyname
  260. is #defined as GetProtoByName in ip.h).  Given a string containing the name of a
  261. network protocol, GetProtoByName will return the integer corresponding to it's
  262. protocol; it will return 0 if it doesn't recognize the protocol.  Currently,
  263. GetProtoByName only understands "tcp" and "udp".
  264.  
  265. This routine differs from the UNIX routine in that it returns a simple int,
  266. rather than a record of information.  This is largely because MacTCP only
  267. understands TCP/IP and UDP/IP.
  268.  
  269.  
  270. GetHostName
  271.  
  272.     int GetHostName(char *name, int namelen)
  273.  
  274. GetHostName emulates the UNIX routine by the same name (gethostname is #defined
  275. as GetHostName). GetHostName returns the name of the local computer in name.  The
  276. routine returns 0 if successful; it will return -1 if an error occurred.
  277.  
  278. Note: Since any given Macintosh may not have a local name (unlike UNIX machines
  279. which DO have local names), GetHostName will return the local host's
  280. dot-separated IP number if no DNS name exists for the local machine.
  281.  
  282. Warning: Currently, namelen is unused, provided only for UNIX compatibility. 
  283. name must point to a "sufficiently large" amount of memory.  This should be fixed
  284. in the future.
  285.  
  286.  
  287. GetHostNameOnly
  288.  
  289.     int GetHostNameOnly(char *name)
  290.  
  291. GetHostNameOnly is a spinoff of GetHostName.  It is identical to GetHostName
  292. except that if the local host doesn't have a DNS name, GetHostNameOnly will fail,
  293. rather than returning a dot-separated IP number.  name should point to a
  294. "sufficiently large" amount of memory.  GetHostNameOnly returns 0 if successful;
  295. otherwise it returns -1.
  296.  
  297.  
  298. GetMyIPDot
  299.  
  300.     int GetMyIPDot(char *num)
  301.  
  302. GetMyIPDot returns the dot-separated IP address of the local machine in num.  num
  303. should point to at least 16 bytes of memory.  GetMyIPDot returns 0 if successful;
  304. otherwise it returns -1.
  305.  
  306. GetMyIPDot isn't part of BSD UNIX sockets.
  307.  
  308.  
  309. GetMyIPNum
  310.  
  311.     unsigned long GetMyIPNum(void)
  312.  
  313. GetMyIPNum returns the unsigned long IP address of the local machine; it returns
  314. -1 if an error occurs.
  315.  
  316. GetMyIPNum isn't part of BSD UNIX sockets.
  317.  
  318.  
  319. getsockname
  320.  
  321.     int getsockname (int sock, struct sockaddr_in *localaddr, int *addrlen)
  322.  
  323. getsockname is identical to the UNIX function with the same name, except
  324. localaddr is a struct sockaddr_in * rather than a struct sockaddr *.  localaddr
  325. points to a sockaddr_in struct containing the port and ip numbers of the local
  326. host. *addrlen will be set to the size of the sockaddr_in struct.  getsockname
  327. returns 0 if successful; otherwise it returns -1.
  328.  
  329. This routine was originally contributed by Lim Wai Kong David
  330. <limwaiko@iscs.nus.sg>.
  331.  
  332.  
  333. GENERAL IP ROUTINES
  334.  
  335.  
  336. socket
  337.  
  338.     int socket(int family, int type, int protocol)
  339.  
  340. socket roughly emulates the UNIX function with the same name.  The variables
  341. family and type are not used, they are provided solely for compatibility with
  342. UNIX code. The variable protocol must be either IPPROTO_TCP or IPPROTO_UDP.
  343. socket also reserves some memory for use by MacTCP.  socket returns a socket
  344. number (currently between 0 and 31 inclusive) if successful; otherwise it returns
  345. -1.
  346.  
  347.  
  348. connect
  349.  
  350.     int connect(int sock, struct sockaddr_in *raddr, int alen)
  351.  
  352. connect roughly emulates the UNIX function with the same name, except localaddr
  353. is a struct sockaddr_in * rather than a struct sockaddr *.  If sock is a TCP
  354. socket,  connect will open a connection from the local host to the remote host
  355. specified in *raddr.  If sock is a UDP socket, the destination specified in raddr
  356. is recorded for use in other routines.  connect returns 0 if successful; it
  357. returns -1 if an error occurs.
  358.  
  359. Note: The variable alen is not used, it is provided solely for compatibility with
  360. UNIX code.
  361.  
  362.  
  363. bind
  364.  
  365.     int bind (int sock, struct sockaddr_in *name, int alen)
  366.  
  367. bind roughly emulates the UNIX function with the same name.  bind specifies a
  368. port for a server to listen to.  sock may be either a UDP or TCP socket.  A port
  369. may be bound to twice; once with a TCP socket, once with a UDP socket.  bind
  370. returns 0 if successful; it returns -1 if an error occurs.
  371.  
  372. Note: bind differs from the UNIX bind in several ways. First of all, name is a
  373. struct sockaddr_in * rather than a struct sockaddr *.  Secondly, name->sin_addr
  374. traditionally is set to INADDR_ANY or the local system address; name->sin_addr is
  375. ignored in this implementation.  Thirdly, in UNIX systems, ports 0 - 1023
  376. (inclusive) are reserved for privilaged processes; this implementation does not
  377. preserve the notion of reserved ports.  Lastly, the variable alen is not used, it
  378. is provided solely for compatibility with UNIX code.
  379.  
  380.  
  381. listen
  382.  
  383.     int listen(int socket, int queuelen)
  384.  
  385. listen is a dummy routine; provided only for UNIX compatibility.  Both variables
  386. are completely ignored.  listen always returns 0.
  387.  
  388. If anyone can think of a way to REALLY implement listen, I'd be glad to hear it.
  389.  
  390.  
  391. write
  392.  
  393.     int write (int sock, Ptr data, int len)
  394.  
  395. write is identical to the UNIX function with the same name.  write sends len
  396. bytes pointed to by data across the active connection referenced by sock.  sock
  397. must be a valid, connected socket;  it can be either a TCP or UDP socket.  write
  398. returns the number of bytes successfully written to the remote host; it returns
  399. -1 if an error prevents any data from being sent.
  400.  
  401.  
  402. read
  403.  
  404.     int read (int sock, Ptr buf, int len)
  405.  
  406. read is identical to the UNIX function with the same name.  read reads at most
  407. len bytes pointed to by data from the active connection referenced by sock.  sock
  408. must be a valid, connected socket;  it can be either a TCP or UDP socket.  If
  409. there is no data outstanding, read will block until new data is received. read
  410. returns the number of bytes successfully read from the remote host; it returns -1
  411. if an error prevents any data from being read.
  412.  
  413.  
  414. close
  415.  
  416.     int close(int sock)
  417.  
  418. close is identical to the UNIX function with the same name.  close closes an
  419. active socket and releases its memory.  close returns 0; it can return -1 if an
  420. error occurs.
  421.  
  422.  
  423. select
  424.  
  425.     int select (int nfds, unsigned long *readfs, struct timeval *timeout)
  426.  
  427. select is used to find out if any unread data is outstanding on a socket before
  428. blocking the process with a read() or similar call.  The argument list is a
  429. truncated version of the original UNIX; I've kept only the aspects of the call
  430. that are important to socket programmers (at least I believe I have).
  431.  
  432. nfds is the number of file descriptors available on the system.  While this can
  433. vary from UNIX system to UNIX system, you can count on the number of file
  434. descriptors known by Simple Sockets being 32 — as defined in ip.h as kNumSockets.
  435. Always pass this constant in as nfds.
  436.  
  437. *readfs specifies the sockets one wants to query.  It is no coincidence that
  438. while there are 32 socket descriptors in Simple Sockets, there are 32 bits in an
  439. unsigned long number.  To specify a particular socket, set it's corresponding bit
  440. to 1; set all other bits to 0.  When select returns, *readfs identifies sockets
  441. with incomming data outstanding in the same way.
  442.  
  443. One can specify a length of time to wait for via *timeout.  If *timeout is nil,
  444. select will poll once before returning, whether or not there is unread data.  If
  445. *timeout is not nil, its fields describe the maximum amount of time select should
  446. wait before giving up and returning to the program.
  447.  
  448. In addition to returning data via *readfs, select itself returns an integer for
  449. error detection.  A return value of 0 indicates success, -1 indicates failure.
  450. Simple Socket's select will only return an error if a socket was flagged that is
  451. not an initialized socket.
  452.  
  453. select is really used by advanced socket programmers — it's not really something
  454. I would expect a novice to understand just from reading this file.  For more
  455. enlightenment, I must refer you to my "Suggested Reading List" (section 8).
  456.  
  457. Note: In the source file ip.c, select is in a section of code labeled "TCP
  458. SECTION".  This is in error; select does infact work with TCP and UDP sockets.
  459.  
  460. Note: This version of select has one fatal flaw: it assumes that if you read from
  461. a socket which has data outstanding you intend to read ALL the data. I have made
  462. some modifications to read() in order to prevent this situation, but it only works
  463. for TCP sockets.
  464.  
  465.  
  466. TCP ROUTINES
  467.  
  468.  
  469. accept
  470.  
  471.     int accept (int sock, struct sockaddr_in *sin, int *alen)
  472.  
  473. accept roughly emulates the UNIX routine by the same name.  accept passively
  474. waits for a TCP connection on socket sock.  When a remote client connects to the
  475. local port described in sock, accept returns a socket number describing the local
  476. connection, and *sin contains the address and port of the client.  Confused?
  477. Please consult Comer and other UNIX texts.
  478.  
  479. Note: sin is a struct sockaddr_in * rather than a struct sockaddr *. Also the
  480. variable alen is not used, it is provided solely for compatibility with UNIX
  481. code.
  482.  
  483.  
  484. UDP ROUTINES
  485.  
  486.  
  487. recvfrom
  488.  
  489.     int recvfrom (int sock, char *buf, int len, int flags, 
  490.                   struct sockaddr_in *sin, int *alen)
  491.  
  492. recvfrom roughly emulates the UNIX routine by the same name.  It allows a program
  493. to passively wait for UDP socket information.  sock is a valid UDP socket, buf
  494. points to a number of bytes in memory, len is the size of memory pointed to by
  495. buf, and *sin contains the address and port of the client upon return.  If *sin 
  496. is nil, packets will be accepted from any client.
  497.  
  498. Note: sin is a struct sockaddr_in * rather than a struct sockaddr *. Also the
  499. variables alen and flags are not used, they are provided solely for compatibility
  500. with UNIX code.
  501.  
  502.  
  503. sendto
  504.  
  505.     int sendto (int sock, char *data, int len, int flags, 
  506.                 struct sockaddr_in *sin, int alen)
  507.  
  508. sendto roughly emulates the UNIX routine by the same name.  It allows a program
  509. to send data across a UDP stream.  sock is a valid UDP socket, data points to a
  510. number of bytes in memory, len is the size of memory pointed to by data, and *sin
  511. contains the address and port of the server.
  512.  
  513. Note: sin is a struct sockaddr_in * rather than a struct sockaddr *. Also the
  514. variables alen and flags are not used, they are provided solely for compatibility
  515. with UNIX code.
  516.  
  517.  
  518. DATA REPRESENTATION (ipdr.c)
  519.  
  520.  
  521.     int htons(int x)
  522.     int ntohs(int x)
  523.     long htonl(long y)
  524.     long ntohl(long y)
  525.  
  526. These routines are provided for UNIX compatibility.  Since the Macintosh byte
  527. ordering is identical to "Network byte ordering" these routines do nothing. They
  528. simply return their arguments.
  529.  
  530.  
  531. 6. Making Your Own Spin Routines
  532. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  533.  
  534. Spin Routines provide simple event processing, allowing the Macintosh to continue
  535. multi-tasking while waiting for a MacTCP call to return.  Rather than processing
  536. events in an event loop, Spin Routines should process only a few events at a time
  537. before returning.
  538.  
  539. A Spin Routine has the following header:
  540.  
  541.     OSErr MySpinRoutine (void)
  542.     
  543. Note:  Because the routine will be called by the Simple Sockets library and not
  544. by the Macintosh operating system, it shouldn't be prefixed with the "pascal"
  545. keyword.
  546.  
  547. These routines can be used to poll for user input even while the program is
  548. waiting for a MacTCP call to return.  For example, the default spin routine
  549. provided by Simple Sockets allows the user to press "esc", which will cause the
  550. current MacTCP call to fail.  One could easily create a window with a Cancel
  551. button, make a socket call, and use a custom Spin Routine to handle that button.
  552.  
  553. For an example Spin Routine, see the file iplow.c; the default spin routine is
  554. named "SpinDefault".
  555.  
  556.  
  557. 7.  Error Handling
  558. ~~~~~~~~~~~~~~~~~~
  559.  
  560. UNIX programs rely on the standard errno variable and other standard functions to
  561. provide error reporting.  Unfortunately, the Macintosh doesn't have anything
  562. quite like that.  Currently, Simple Sockets provides similar error reporting with
  563. two global variables:  gErrno and gMacErrno.  gErrno is essentially the same as
  564. the UNIX errno variable; gMacErrno will contain the normal Macintosh OSErr error
  565. number if the error was caused by a Macintosh routine.  If an error occurs, make
  566. sure you check both variables.
  567.  
  568. By my own admission, error reporting in Simple Sockets is pretty weak.  This
  569. should improve in the future.
  570.  
  571.  
  572. 8.  Suggested Reading List
  573. ~~~~~~~~~~~~~~~~~~~~~~~~~~
  574.  
  575. The following is a list of works I suggest looking into if you are interested in
  576. socket or MacTCP programming.  This list includes books, electronic documents,
  577. World Wide Web pages, and the like.
  578.  
  579.  
  580. Apple Computer, Inc.. MacTCP Programmer's Guide, Apple Computer, Inc., 1991.
  581. (available via WWW at one of Apple's many Web servers)
  582.  
  583. Comer, Douglas E., David L. Stevens.  Internetworking with TCP/IP, Volume III.
  584.     Prentice Hall: Englewood Cliffs, New Jersey.
  585.     
  586. Lentz, Robert.  Robert Lentz's Macintosh Programming Resources. WWW Pages.
  587. (URL: http://www.astro.nwu.edu/lentz/mac/programming/home-prog.html)
  588.  
  589. Stevens, Richard W.. UNIX Network Programming. Prentice Hall: Englewood Cliffs,
  590.     New Jersey.
  591.  
  592.  
  593. 9.  Simple Sockets License Agreement
  594. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  595.  
  596. Simple Sockets is offered directly to the public domain. I request that it is
  597. not modified in any way and that it is accompanied by all of the original
  598. documentation unaltered. This is only a request.
  599.  
  600. Disclaimer of warranty:
  601. In using this software, you understand and agree that this software is provided
  602. “as is” without warranty of any kind.  The entire risk as to the results and
  603. performance of using this software lies entirely with you, the user.  The author
  604. does not make any warranties, either expressed or implied, including but not
  605. limited to implied warranties of merchantability and fitness for a particular
  606. purpose, with respect to this software.
  607.  
  608. In no event shall the author be liable for any consequential, incidental, or
  609. special damages whatsoever (including without limitation damages for loss of
  610. critical data, loss of profits, interruption of business, and the like) arising
  611. out of the use or inability to use this software.  Because some states do not
  612. allow the exclusion or limitation of liability for consequential or incidental
  613. damages, the above limitations may not apply to you.
  614.  
  615. Although the author would appreciate any feedback and bug reports, the author
  616. shall not be responsible for correcting any problems which you discover or
  617. otherwise help you maintain and use this software.  Furthermore, the author may
  618. at any time replace, modify, alter, improve, enhance or change this software.
  619.  
  620. Complete agreement:
  621. This agreement constitutes the entire agreement and supersedes any prior
  622. agreements between you and the author concerning this software.  This agreement
  623. cannot be amended, modified, or waived except in writing.
  624.  
  625. General:
  626. If any provision of this agreement shall be found to be unenforceable, it shall
  627. be deemed severed from the remainder of this agreement.
  628.